package io.jnet.common.api.impl;

import java.io.IOException;
import java.nio.channels.AsynchronousSocketChannel;
import com.jfireframework.baseutil.collection.buffer.ByteBuf;
import com.jfireframework.baseutil.collection.buffer.DirectByteBuf;
import com.jfireframework.baseutil.resource.ResourceCloseAgent;
import com.jfireframework.baseutil.resource.ResourceCloseCallback;
import io.jnet.common.api.ChannelContext;
import io.jnet.common.api.WriteHandler;
import io.jnet.common.bufstorage.BufStorage;
import io.jnet.common.decodec.FrameDecodec;
import io.jnet.common.streamprocessor.StreamProcessor;
import io.jnet.common.util.AioListener;

public abstract class BaseChannelContext implements ChannelContext
{
    protected final WriteHandler                       writeHandler;
    protected final BufStorage                         bufStorage;
    protected final ByteBuf<?>                         ioBuf;
    protected final StreamProcessor[]                  processors;
    protected final AsynchronousSocketChannel          socketChannel;
    protected final ResourceCloseAgent<ChannelContext> closeAgent = new ResourceCloseAgent<ChannelContext>(this, new ResourceCloseCallback<ChannelContext>() {
                                                                      
                                                                      @Override
                                                                      public void onClose(ChannelContext resource)
                                                                      {
                                                                          try
                                                                          {
                                                                              socketChannel.close();
                                                                          }
                                                                          catch (IOException e)
                                                                          {
                                                                              e.printStackTrace();
                                                                          }
                                                                          finally
                                                                          {
                                                                              ioBuf.release();
                                                                          }
                                                                      }
                                                                  });
    
    public BaseChannelContext(//
            BufStorage bufStorage, //
            int maxMerge, //
            AioListener serverListener, //
            StreamProcessor[] processors, //
            AsynchronousSocketChannel socketChannel, //
            FrameDecodec frameDecodec)
    {
        this.socketChannel = socketChannel;
        this.processors = processors;
        this.bufStorage = bufStorage;
        ioBuf = DirectByteBuf.allocate(128);
        writeHandler = new DefaultWriteHandler(maxMerge, socketChannel, serverListener, bufStorage, this);
    }
    
    @Override
    public void registerWrite()
    {
        writeHandler.registerWrite();
    }
    
    @Override
    public boolean close()
    {
        return closeAgent.close();
    }
    
    @Override
    public boolean isOpen()
    {
        return socketChannel.isOpen();
    }
    
    @Override
    public StreamProcessor[] processors()
    {
        return processors;
    }
    
    @Override
    public BufStorage bufStorage()
    {
        return bufStorage;
    }
    
    @Override
    public AsynchronousSocketChannel socketChannel()
    {
        return socketChannel;
    }
    
}
